﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include "BurnDlg3X.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QAbstractItemView>
#include <QTimer>
#include "BurnCtrl/BurnCtrlFaction.h"

namespace BurnDlg {

namespace  {
    const int NUMBER_VALUE_THREE = 3;
    const int COLUMN_MINIMUM_HEIGHT_SIZE_192 = 192;
    const int COLUMN_MINIMUM_HEIGHT_SIZE_400 = 400;
    const int COLUMN_WIDTH_SIZE_20 = 20;
    const int COLUMN_WIDTH_SIZE_100 = 100;
    const int COLUMN_WIDTH_SIZE_200 = 200;
    const int COLUMN_WIDTH_SIZE_300 = 300;
    const int COLUMN_WIDTH_SIZE_500 = 500;
    const int CONFIG_TIMER_START = 100;
    const int MAX_BURN_NUM = 20;
}

BurnDlg3X::BurnDlg3X(ChipType chipType, QWidget *pParent)
    : BurnDlg(pParent),
      ui(new Ui::BurnDlg3X),
      actSettings(new QAction(stringClass.GetActionSettings())),
      actImportConfig(new QAction(stringClass.GetActionImportConfig())),
      actSaveConfig(new QAction(stringClass.GetActionSaveConfig())),
      configTimer(nullptr),
      actChangeChip(new QAction(stringClass.GetChangeChip())),
      actAbout(new QAction(stringClass.GetAbout())),
      isMultipleBurnOpen(false),
      multipleBurnDlg(nullptr)
{
    this->chipType = chipType;
    burnInfo.clear();
    binModel = new BinFileModel();
    if (ui != nullptr && actSettings != nullptr && actImportConfig != nullptr &&
        actSaveConfig != nullptr && actChangeChip != nullptr && actAbout != nullptr &&
        actEnglish != nullptr && actChinese != nullptr) {
        ui->setupUi(this);
        this->BurnDlg3X::InitBurnCtrl();
        ui->menuSetting->addAction(actSettings);
        ui->menuSetting->addAction(actImportConfig);
        ui->menuSetting->addAction(actSaveConfig);
        ui->menuSetting->addMenu(menuWifiLanguage);
        ui->menuOption->addAction(actChangeChip);
        ui->menuHelp->addAction(actAbout);
        ui->progressBarReceive->setRange(0, SHRT_MAX);
        ui->progressBarReceive->setValue(0);
        ui->textEditReceive->setReadOnly(true);
        ui->textEditReceive->setTextInteractionFlags(Qt::NoTextInteraction);
        ui->lineEditSeleteFile->setFocusPolicy(Qt::NoFocus);
    }
    QString fileName = QCoreApplication::applicationDirPath() + "\\configure";
    QSettings cfg(fileName + "\\config_setting.ini", QSettings::IniFormat);
    isCheckAble = cfg.value("editable_checkbox/EDITABLE").toBool();
    InitConnect();
    InitTableView();
    InitMenus();
    SlotCbnSetfocusComboCom();
    if (burnCtrl != nullptr) {
        burnCtrl->StartWiteMonitoring();
    }
    if (isCheckAble) {
        configTimer = new QTimer(this);
        if (configTimer != nullptr) {
            connect(configTimer, &QTimer::timeout, this, &BurnDlg3X::SlotConfigTimerTimeOut);
            configTimer->start(CONFIG_TIMER_START);
        }
    } else {
        LoadDlgConfig();
    }
    if (ui != nullptr) {
        if (chipType != ChipType::SPARTA) {
            ui->btnEraseAll->hide();
        }
        ui->verson->hide();
    }
}

BurnDlg3X::~BurnDlg3X()
{
    if (ui != nullptr) {
        delete ui;
        ui = nullptr;
    }

    if (actSettings != nullptr) {
        delete actSettings;
        actSettings = nullptr;
    }

    if (actImportConfig != nullptr) {
        delete actImportConfig;
        actImportConfig = nullptr;
    }

    if (actSaveConfig != nullptr) {
        delete actSaveConfig;
        actSaveConfig = nullptr;
    }

    if (actChangeChip != nullptr) {
        delete actChangeChip;
        actChangeChip = nullptr;
    }

    if (actAbout != nullptr) {
        delete actAbout;
        actAbout = nullptr;
    }

    if (binModel != nullptr) {
        delete binModel;
        binModel = nullptr;
    }

    if (configTimer != nullptr) {
        delete configTimer;
        configTimer = nullptr;
    }

    if (multipleBurnDlg != nullptr) {
        delete multipleBurnDlg;
        multipleBurnDlg = nullptr;
    }
    if (encryptBuffer.bufferData != nullptr) {
        delete [] encryptBuffer.bufferData;
        encryptBuffer.bufferData = nullptr;
    }
    encryptBuffer.bufferLen = 0;
}

void BurnDlg3X::SlotConfigTimerTimeOut()
{
    if (configTimer == nullptr) {
        return;
    }
    configTimer->stop();
    delete configTimer;
    configTimer = nullptr;
    QString pathDlg3X = DataConvertor::GetBurnToolConfigPathNew();
    QFile file(pathDlg3X);
    if (file.exists()) {
        if (QMessageBox::information(this, tr("BurnTool"), stringClass.GetLoadExistingConfig(),
                                     stringClass.GetYes(), stringClass.GetNo()) != 0) {
            return;
        }
    } else {
        return;
    }
    LoadDlgConfig();
}

void BurnDlg3X::InitTableView() const
{
    if (binModel == nullptr) {
        return;
    }
    binModel->SetEditableCheckbox(isCheckAble);
    if (ui != nullptr) {
        ui->tableView->setModel(binModel);
        ui->tableView->setDragEnabled(true);
        ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
        ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->tableView->setDefaultDropAction(Qt::MoveAction);
        ui->tableView->setDragDropMode(QAbstractItemView::InternalMove);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_CHECK, COLUMN_WIDTH_SIZE_20);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_ADD, COLUMN_WIDTH_SIZE_20);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_DELETE, COLUMN_WIDTH_SIZE_20);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_NAME, COLUMN_WIDTH_SIZE_100);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_PAHT, COLUMN_WIDTH_SIZE_200);
        ui->tableView->setMinimumHeight(COLUMN_MINIMUM_HEIGHT_SIZE_192);
        ui->tableView->horizontalHeader()->setSectionResizeMode(TABLEVIEW_COLUMN_CHECK, QHeaderView::Fixed);
        ui->tableView->horizontalHeader()->setSectionResizeMode(TABLEVIEW_COLUMN_ADD, QHeaderView::Fixed);
        ui->tableView->horizontalHeader()->setSectionResizeMode(TABLEVIEW_COLUMN_DELETE, QHeaderView::Fixed);
    }
}

void BurnDlg3X::InitMenus()
{
    this->tableViewMenu = new QMenu(this);
    QAction *createNewFileAction = new QAction(stringClass.GetCreateNewFile());
    if (createNewFileAction != nullptr) {
        this->tableViewMenu->addAction(createNewFileAction);
        connect(createNewFileAction, &QAction::triggered, this, &BurnDlg3X::SlotCreateNewFwpkgFile);
    }
    QAction *saveSpiltFileAction = new QAction(stringClass.GetSaveSplitFile());
    if (saveSpiltFileAction != nullptr) {
        this->tableViewMenu->addAction(saveSpiltFileAction);
        connect(saveSpiltFileAction, &QAction::triggered, this, &BurnDlg3X::SlotSaveSpiltFwpkgFile);
    }
}

void BurnDlg3X::contextMenuEvent(QContextMenuEvent *event)
{
    Q_UNUSED(event);
    if (!ui->tableView->selectionModel()->currentIndex().isValid()) {
        return;
    }
    this->tableViewMenu->exec(QCursor::pos());
}

void BurnDlg3X::SlotCreateNewFwpkgFile()
{
    CreateNewFwpkgFile(ui->lineEditSeleteFile->text());
}

void BurnDlg3X::SlotSaveSpiltFwpkgFile()
{
    SaveSpiltFwpkgFile(ui->lineEditSeleteFile->text());
}

void BurnDlg3X::InitBurnCtrl()
{
    BurnCtrlFaction faction;
    burnCtrl = faction.GetBurnCtrl(chipType);
    if (burnCtrl != nullptr) {
        burnCtrl->SetBurnDlg(this);
    }
}

void BurnDlg3X::InitConnect()
{
    // setting
    if (actSettings != nullptr) {
        connect(actSettings, &QAction::triggered, this, &BurnDlg3X::SlotShowMenuSettings);
    }
    if (actSaveConfig != nullptr) {
        connect(actSaveConfig, &QAction::triggered, this, &BurnDlg3X::SlotSaveConfig);
    }
    if (actImportConfig != nullptr) {
        connect(actImportConfig, &QAction::triggered, this, &BurnDlg3X::SlotImportConfig);
    }
    if (actChangeChip != nullptr) {
        connect(actChangeChip, &QAction::triggered, this, &BurnDlg3X::SlotShowChangeChip);
    }
    // help
    if (actAbout != nullptr) {
        connect(actAbout, &QAction::triggered, this, &BurnDlg3X::SlotShowAbout);
    }
    if (ui != nullptr) {
        // button
        connect(ui->btnSelectFile, &QPushButton::clicked, this, &BurnDlg3X::SlotBnClickedButtonSelectfile);
        connect(ui->btnStartBurn, &QPushButton::clicked, this,  &BurnDlg3X::SlotBnClickedButtonStartburn);
        connect(ui->btnMultipleBurn, &QPushButton::clicked, this, &BurnDlg3X::SlotBnClickedMultipleBurn);
        connect(ui->btnSelectTarget, &QPushButton::clicked, this, &BurnDlg3X::SlotBnClickedSelectTarget);
        connect(ui->btnExport, &QPushButton::clicked, this, &BurnDlg3X::SlotBnClickedExport);
        connect(ui->btnEraseAll, &QPushButton::clicked, this, &BurnDlg3X::SlotBnClickedEraseAll);

        // tableView
        connect(ui->tableView->horizontalHeader(), &QHeaderView::sectionClicked, this,
                &BurnDlg3X::SlotBnClickedTableHeader);
        connect(ui->tableView, &QTableView::clicked, this, &BurnDlg3X::SlotBnClickedTableView);
        connect(ui->tableView, &QTableView::doubleClicked, this, &BurnDlg3X::SlotBnDoubleClickedTableView);
        // comboBox
        connect(ui->comboBoxCom, &ComboBoxCom::Clicked, this, &BurnDlg3X::SlotCbnSetfocusComboCom);
    }
    // burnctrl
    if (burnCtrl != nullptr) {
        connect(burnCtrl, &BurnCtrl::SignalOpenComFail, this, &BurnDlg3X::SlotOpenComFail);
        connect(burnCtrl, &BurnCtrl::SignalBurnFileFinish, this, &BurnDlg3X::SlotBurnFileFinish);
        connect(burnCtrl, &BurnCtrl::SignalInsertPlainText, this, &BurnDlg3X::SlotInsertPlainText);
        connect(burnCtrl, &BurnCtrl::SignalBurnFileFailed, this, &BurnDlg3X::SlotBurnFileFailed);
        connect(burnCtrl, &BurnCtrl::SignalSetProgressValue, this, &BurnDlg3X::SlotSetProgress);
        connect(burnCtrl, &BurnCtrl::SignalShowQMessageBox, this, &BurnDlg3X::SlotShowQMessageBox);
        connect(burnCtrl, &BurnCtrl::SignalExportfail, this, &BurnDlg3X::SlotExportFail);
        connect(burnCtrl, &BurnCtrl::SignalExportSuccess, this, &BurnDlg3X::SlotExportSuccess);
        connect(burnCtrl, &BurnCtrl::SignalEraseSuccess, this, &BurnDlg3X::SlotEraseSuccess);
        connect(burnCtrl, &BurnCtrl::SignalEraseFail, this, &BurnDlg3X::SlotEraseFail);
    }
}

void BurnDlg3X::SlotShowMenuSettings()
{
    BurnDlg::SlotShowMenuSettings();
    if (setting != nullptr && burnCtrl != nullptr) {
        setting->SetMultipleBurnParam(burnCtrl->GetMultiBurnTotalNum(),
                                      burnCtrl->GetMultiBurnNumPerLine(), true, false);
        setting->SetIsResetAfterSuccess(burnCtrl->GetIsResetAfterSuccess());
        setting->SetCurrentValue();
        setting->Set3XSettingShow(chipType);
    }
}

void BurnDlg3X::SlotOpenComFail()
{
    RemoveTempDir();
    if (ui != nullptr) {
        QMessageBox::warning(nullptr, "", stringClass.GetIdsString32812(). \
                             arg(ui->comboBoxCom->currentText().mid(NUMBER_VALUE_THREE)));
        ui->btnStartBurn->setText(stringClass.GetStartBurn());
        ui->btnExport->setText(stringClass.GetExportStart());
    }
}

void BurnDlg3X::SlotSaveConfig()
{
    SaveDlgConfig();
    QString path = DataConvertor::GetBurnToolConfigPathNew();
    if (QMessageBox::information(this, stringClass.GetInformation(), stringClass.GetOutPutConfigFile(),
                                 stringClass.GetYes(), stringClass.GetNo()) == 1) {
        return;
    }
    QString filePath = QFileDialog::getSaveFileName(this, tr("Select File"), "", stringClass.GetIdsString33074());
    if (filePath.isEmpty() || path == filePath) {
        return;
    }
    QFile file(filePath);
    if (file.exists()) {
        int ret = QMessageBox::warning(this, "", stringClass.GetIdsString33075(),
                                       stringClass.GetYes(), stringClass.GetNo());
        if (ret == 1) {
            return;
        }
        file.remove();
    }
    file.copy(path, filePath);
}

void BurnDlg3X::SaveDlgConfig()
{
    QString configPathFile = DataConvertor::GetBurnToolConfigPathNew();
    QFile file(configPathFile);
    if (file.exists()) {
        // 存在
        int result = QMessageBox::information(this, stringClass.GetInformation(),
                                              stringClass.GetIdsString33075(),
                                              stringClass.GetYes(), stringClass.GetNo());
        if (result == 1) {
            return;
        }
    }
    if (!(file.open(QIODevice::ReadWrite | QIODevice::Text))) {
        return;
    }
    file.close();
    // 保存串口设置
    SavedComConfig2File(configPathFile);
    // 保存文件信息
    SavedBinInfoConfig2File(configPathFile);
    // 保存窗口信息
    SavedWinInfoConfig2File(configPathFile);
}

void BurnDlg3X::SavedComConfig2File(const QString &path) const
{
    int baud = 0;
    int databits = 0;
    int stopbits = 0;
    QSerialPort::Parity parity = QSerialPort::UnknownParity;
    int flowctrl = 0;
    if (burnCtrl != nullptr) {
        burnCtrl->GetComSetting(baud, databits, stopbits, parity, flowctrl);
    }
    QSettings cfg(path, QSettings::IniFormat);
    cfg.setValue(COM_CONFIG + "/" + INI_BAUD, QString::number(baud));
    cfg.setValue(COM_CONFIG + "/" + INI_DATABIT, QString::number(databits));
    cfg.setValue(COM_CONFIG + "/" + INI_STOPBIT, QString::number(stopbits));
    cfg.setValue(COM_CONFIG + "/" + INI_PARITY, QString::number(parity));
    cfg.setValue(COM_CONFIG + "/" + INI_FLOWCTRL, QString::number(flowctrl));
    if (ui != nullptr) {
        QString currentCom = ui->comboBoxCom->currentText();
        cfg.setValue(COM_CONFIG + "/" + INI_COM, currentCom);
    }
}

void BurnDlg3X::SavedBinInfoConfig2File(const QString &path) const
{
    if (binModel == nullptr) {
        return;
    }
    QMap<int, BIN_INFO> info = binModel->GetBinFileInfoData();
    QSettings cfg(path, QSettings::IniFormat);
    for (int i = 0; i < info.size(); i++) {
        BIN_INFO item = info[i];
        cfg.setValue(FILE_CONFIG + "/" + INI_FILE_CHECK + QString::number(i), QString::number(binModel->GetCheck(i)));
        cfg.setValue(FILE_CONFIG + "/" + INI_FILE_PATH + QString::number(i), item.path);
        cfg.setValue(FILE_CONFIG + "/" + INI_FILE_NAME + QString::number(i), item.fileName);
        cfg.setValue(FILE_CONFIG + "/" + INI_FILE_INDEX + QString::number(i), item.fileIndex);
        cfg.setValue(FILE_CONFIG + "/" + INI_FILE_SIZE + QString::number(i), item.fileSize);
        cfg.setValue(FILE_CONFIG + "/" + INI_BURN_ADDR + QString::number(i), item.burnAddr);
        cfg.setValue(FILE_CONFIG + "/" + INI_BURN_SIZE + QString::number(i), item.burnSize);
        cfg.setValue(FILE_CONFIG + "/" + INI_FILE_TYPE + QString::number(i),
                     QString::number(static_cast<int>(item.type)));
    }
}

void BurnDlg3X::SavedWinInfoConfig2File(const QString &path) const
{
    QSettings cfg(path, QSettings::IniFormat);
    if (burnCtrl != nullptr) {
        cfg.setValue(DLG_CONFIG + "/" + "YMODEM_PACKAGE_SIZE", QString::number(burnCtrl->GetYModemEachPackageSize()));
        cfg.setValue(DLG_CONFIG + "/" + "RESET_AFTER_SUCCESS", QString::number(burnCtrl->GetIsResetAfterSuccess()));
        cfg.setValue(DLG_CONFIG + "/" + "DLG_BURN_NUM", QString::number(burnCtrl->GetMultiBurnTotalNum()));
        cfg.setValue(DLG_CONFIG + "/" + "DLG_ONE_LINE_NUM", QString::number(burnCtrl->GetMultiBurnNumPerLine()));
    }
}

void BurnDlg3X::SlotImportConfig()
{
    QString path = DataConvertor::GetBurnToolConfigPathNew();
    if (burnCtrl == nullptr || burnCtrl->IsBusy()) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }

    QString filePath = QFileDialog::getOpenFileName(this, tr("Select File"), "", stringClass.GetIdsString33074());
    if (filePath.isEmpty() || path == filePath) {
        return;
    }
    QFile file(path);
    if (file.exists()) {
        if (QMessageBox::warning(nullptr, "", stringClass.GetIdsString33075(),
                                 stringClass.GetYes(), stringClass.GetNo()) == 1) {
            return;
        }
        file.remove();
    }
    file.copy(filePath, path);
    QSettings cfg(path, QSettings::IniFormat);
    int chipTypeIni = cfg.value(DLG_CONFIG + "/" + "CHIP_TYPE").toInt();
    if (chipTypeIni != static_cast<int>(Global::currentChipTypeId)) {
        QSettings cfg2(Global::GetAppConfigPath() + "\\config_chip_type.ini", QSettings::IniFormat);
        cfg2.setValue("ChipType/CurrentChipTypeId", QString::number(chipTypeIni));
        Global::CloseApp(QAPP_EXIT_VALUE);
    }
    LoadDlgConfig();
}

void BurnDlg3X::LoadDlgConfig() const
{
    QString path = DataConvertor::GetBurnToolConfigPathNew();

    LoadComConfigFromFile(path);
    LoadFileConfigFromFile(path);
}

void BurnDlg3X::LoadComConfigFromFile(const QString &path) const
{
    if (burnCtrl == nullptr) {
        return;
    }
    unsigned int ret = 1;
    QSettings cfg(path, QSettings::IniFormat);
    QVariant ascReturnedBaud = cfg.value(COM_CONFIG + "/" + INI_BAUD);
    ret &= static_cast<unsigned int>(ascReturnedBaud.isValid());
    int baud = ascReturnedBaud.toInt();
    QVariant ascReturnedDataBit = cfg.value(COM_CONFIG + "/" + INI_DATABIT);
    ret &= static_cast<unsigned int>(ascReturnedDataBit.isValid());
    int databits = ascReturnedDataBit.toInt();
    QVariant ascReturnedStopBit = cfg.value(COM_CONFIG + "/" + INI_STOPBIT);
    ret &= static_cast<unsigned int>(ascReturnedStopBit.isValid());
    int stopbits = ascReturnedStopBit.toInt();
    QVariant ascReturnedParity = cfg.value(COM_CONFIG + "/" + INI_PARITY);
    ret &= static_cast<unsigned int>(ascReturnedParity.isValid());
    QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(ascReturnedParity.toInt());
    QVariant ascReturnedFlowCtrl = cfg.value(COM_CONFIG + "/" + INI_FLOWCTRL);
    ret &= static_cast<unsigned int>(ascReturnedFlowCtrl.isValid());
    int flowCtrl = ascReturnedBaud.toInt();
    if (ret == 1) {
        burnCtrl->UpdateComSetting(baud, databits, stopbits, parity, flowCtrl);
    }

    burnCtrl->SetIsResetAfterSuccess(cfg.value(DLG_CONFIG + "/" + "RESET_AFTER_SUCCESS").toBool());
    int burnNum = cfg.value(DLG_CONFIG + "/" + "DLG_BURN_NUM").toUInt();
    if (burnNum > MAX_BURN_NUM) {
        burnNum = MAX_BURN_NUM;
    }
    burnCtrl->SetMultiBurnTotalNum(burnNum);
    burnCtrl->SetMultiBurnNumPerLine(cfg.value(DLG_CONFIG + "/" + "DLG_ONE_LINE_NUM").toUInt());
    burnCtrl->SetYModemEachPackageSize(cfg.value((DLG_CONFIG + "/" + "YMODEM_PACKAGE_SIZE")).toUInt());
}

void BurnDlg3X::LoadFileConfigFromFile(const QString &path) const
{
    QMap<int, BIN_INFO> infoMap;
    QSettings cfg(path, QSettings::IniFormat);
    QMap<int, BIN_INFO> mapBinInfo;
    mapBinInfo.clear();
    for (unsigned int i = 0; i < EFUSE_ITEM_MAX; ++i) {
        BIN_INFO info;
        unsigned int ret = BurnDlg::LoadFileConfigFromFileGetInfo(info, cfg, i);
        if (ret == 0) {
            break;
        }
        mapBinInfo[i] = info;
    }
    if (binModel == nullptr) {
        return;
    }
    binModel->FetchData(mapBinInfo);
    QMap<int, bool> mapCheck;
    for (unsigned int i = 0; i < EFUSE_ITEM_MAX; ++i) {
        bool ret = true;
        QVariant check = cfg.value(FILE_CONFIG + "/" + INI_FILE_CHECK + QString::number(i));
        ret = check.isValid();
        if (!ret) {
            break;
        }
        mapCheck[i] = check.toBool();
    }
    binModel->FetchData(mapCheck);
    if (ui != nullptr) {
        ui->lineEditSeleteFile->setText(mapBinInfo[0].path);
    }
}

void BurnDlg3X::SlotBnClickedButtonSelectfile()
{
    QString filePath = QFileDialog::getOpenFileName(this, tr("Select File"), "", stringClass.GetIdsString32941());
    if (!filePath.isEmpty()) {
        AnalyseBinFile(filePath);
    }
}

void BurnDlg3X::AnalyseBinFile(QString filePath)
{
    if (burnCtrl == nullptr || burnCtrl->IsBusy()) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }
    if (ui == nullptr || binModel == nullptr) {
        return;
    }
    ui->lineEditSeleteFile->setText(filePath);
    QMap<int, bool> mapLastBinCheck = binModel->GetMapCheck();
    QMap<int, BIN_INFO> mapLastBinInfo = binModel->GetMapBinFileInfo();
    binModel->ClearData();
    BIN_INFO_ARRAY infoArray;
    QString version;
    QMap<int, BIN_INFO> mapBinInfo = binModel->GetMapBinFileInfo();
    DataConvertor::AnalysMultifBin(ui->lineEditSeleteFile->text(), infoArray, version,
                                   isEncrypt, encryptBuffer);
    for (int i = 0; i < infoArray.GetSize(); i++) {
        if (infoArray.GetAt(i).type == IMAGE_TYPE::IMAGE_TYPE_SMALL_SSB ||
            infoArray.GetAt(i).type == IMAGE_TYPE::IMAGE_TYPE_SMALL_SSB_SHA) {
            continue;
        }
        mapBinInfo[mapBinInfo.size()] = infoArray.GetAt(i);
    }
    QMap<int, bool> mapCheck;
    if (!isCheckAble) {
        AnalyseBinFileSub(mapBinInfo, mapCheck, mapLastBinInfo, mapLastBinCheck);
    } else {
        for (int i = 0; i < mapBinInfo.size(); i++) {
            mapCheck[i] = true;
        }
    }
    binModel->FetchData(mapCheck);
    binModel->FetchData(mapBinInfo);
    UpdateVersion(version);
}

void BurnDlg3X::AnalyseBinFileSub(QMap<int, BIN_INFO> &mapBinInfo, QMap<int, bool> &mapCheck,
                                  QMap<int, BIN_INFO> &mapLastBinInfo,
                                  QMap<int, bool> &mapLastBinCheck) const
{
    for (int i = 0; i < mapBinInfo.size(); i++) {
        int j = 0;
        for (; j < mapLastBinInfo.size(); j++) {
            if (mapBinInfo[i].fileName.compare(mapLastBinInfo[j].fileName) == 0) {
                mapCheck[i] = mapLastBinCheck[j];
                break;
            }
        }
        if (j == mapLastBinInfo.size()) {
            mapCheck[i] = true;
        }
    }
}

void BurnDlg3X::UpdateVersion(const QString &version) const
{
    if (ui == nullptr) {
        return;
    }
    if (!version.isEmpty()) {
        QString strVersion = tr("Version ") + version;
        ui->verson->setText(strVersion);
    } else {
        ui->verson->setText(version);
    }
}

bool BurnDlg3X::ConfigComPort()
{
    if (ui == nullptr) {
        return false;
    }
    QString strPort = ui->comboBoxCom->currentText();
    if (ui->comboBoxCom->findText(strPort) != -1) {
        ui->comboBoxCom->setCurrentText(strPort);
    } else {
        return false;
    }
    if (ui->comboBoxCom->count() == 0) {
        QMessageBox::warning(this, "", stringClass.GetIdsString32899());
        return false;
    } else {
        int com = strPort.mid(3).toInt();
        if (burnCtrl != nullptr) {
            burnCtrl->SetComNum(com);
            return true;
        }
        return false;
    }
}

void BurnDlg3X::changeEvent(QEvent* event)
{
    if (ui == nullptr) {
        return;
    }
    if (lastWinStates == windowState()) {
        QWidget::changeEvent(event);
        return;
    }
    if (windowState() == Qt::WindowMaximized) {
        lastWinStates = windowState();
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_NAME, COLUMN_WIDTH_SIZE_300);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_PAHT, COLUMN_WIDTH_SIZE_500);
        ui->tableView->setMinimumHeight(COLUMN_MINIMUM_HEIGHT_SIZE_400);
    } else if (windowState() == Qt::WindowNoState) {
        lastWinStates = windowState();
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_NAME, COLUMN_WIDTH_SIZE_100);
        ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_PAHT, COLUMN_WIDTH_SIZE_200);
        ui->tableView->setMinimumHeight(COLUMN_MINIMUM_HEIGHT_SIZE_192);
    }
    QWidget::changeEvent(event);
}

void BurnDlg3X::SlotBnClickedButtonStartburn()
{
    if (burnCtrl == nullptr || ui == nullptr || binModel == nullptr) {
        return;
    }

    if (!ConfigComPort()) {
        return;
    }

    if (isMultipleBurnOpen) {
        return;
    }

    if (ui->btnStartBurn->text() == stringClass.GetStartBurn()) {
        UpdateList();
        burnInfo.clear();
        ui->progressBarReceive->setValue(0);
        burnCtrl->SetIsCancel(FALSE);
        SlotInsertPlainText(stringClass.GetIdsString32897());
        int i = 0;
        QMap<int, BIN_INFO> binInfo = binModel->GetMapBinFileInfo();
        QMap<int, BIN_INFO> checkBinInfo;
        QMap<int, bool> binCheck = binModel->GetMapCheck();
        for (auto it = binInfo.begin(); it != binInfo.end(); it++) {
            if (binCheck[it.key()] && it->type == IMAGE_TYPE::IMAGE_TYPE_LOADER) {
                BIN_INFO_ARRAY infoArray;
                QString version;
                DataConvertor::AnalysMultifBin(ui->lineEditSeleteFile->text(), infoArray, version,
                                               isEncrypt, encryptBuffer);
                PriorityBurn(infoArray, checkBinInfo, i);
            }

            if (binCheck[it.key()] &&
                (it->type == IMAGE_TYPE::IMAGE_TYPE_LOADER ||
                it->type >= IMAGE_TYPE::IMAGE_TYPE_APP_3321)) {
                checkBinInfo[i++] = it.value();
            }
        }
        ui->textEditReceive->clear();
        if (checkBinInfo.size() == 0 || (!QFile(ui->lineEditSeleteFile->text()).exists())) {
            QMessageBox::warning(nullptr, tr("BurnTool"), stringClass.GetNoValidFlashFile());
            ui->btnStartBurn->setText(stringClass.GetStartBurn());
            return;
        }
        burnCtrl->InitBurnCmdByArray(checkBinInfo);
        ui->btnStartBurn->setText(stringClass.GetStopBurn());
        emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_STARTCONNECT), 0, 0);
    } else {
        burnCtrl->SetIsCancel(TRUE);
        burnCtrl->BurnCtrlCancel();
    }
}

void BurnDlg3X::PriorityBurn(const BIN_INFO_ARRAY &infoArray,
    QMap<int, BIN_INFO> &checkBinInfo, int &i) const
{
    for (int j = 0; j < infoArray.GetSize(); j++) {
        if (infoArray.GetAt(j).type == IMAGE_TYPE::IMAGE_TYPE_SMALL_SSB) {
            checkBinInfo[i++] = infoArray.GetAt(j);
        }
    }
}

void BurnDlg3X::SlotInsertPlainText(const QString &editStr)
{
    if (ui == nullptr) {
        return;
    }
    ui->textEditReceive->insertPlainText(editStr);
    ui->textEditReceive->ensureCursorVisible();
    ui->textEditReceive->setFocus();
}

void BurnDlg3X::SlotCbnSetfocusComboCom() const
{
    if (ui == nullptr) {
        return;
    }
    if (portType == Base::TCP_PORT) {
        return;
    }
    QString strPort = ui->comboBoxCom->currentText();
    ui->comboBoxCom->clear();
    QStringList strListPort;
    DataConvertor::RefreshComList(strListPort);
    ui->comboBoxCom->addItems(strListPort);
    for (int i = 0; i < strListPort.size(); i++) {
        if (strListPort.at(i) == strPort) {
            ui->comboBoxCom->setCurrentText(strPort);
        }
    }
}

void BurnDlg3X::SlotBurnFileFinish()
{
    if (ui == nullptr) {
        return;
    }
    RemoveTempDir();
    ui->btnStartBurn->setText(stringClass.GetStartBurn());
    ui->progressBarReceive->setValue(SHRT_MAX);
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
    SlotInsertPlainText(stringClass.GetIdsString32880() + "\n");
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
}

void BurnDlg3X::SlotBurnFileFailed()
{
    if (ui == nullptr) {
        return;
    }
    RemoveTempDir();
    ui->btnStartBurn->setText(stringClass.GetStartBurn());
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
    SlotInsertPlainText(stringClass.GetIdsString32881());
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
    ui->progressBarReceive->setValue(0);
}

void BurnDlg3X::RemoveTempDir() const
{
    if (ui == nullptr) {
        return;
    }
    QString saveDir = QCoreApplication::applicationDirPath() + "/tempFile" + "_"
            + QString::number(ui->comboBoxCom->currentText().mid(3).toInt());
    QDir dir(saveDir);
    if (dir.exists()) {
        dir.removeRecursively();
    }
}

void BurnDlg3X::SlotSetProgress(double pos) const
{
    if (ui == nullptr) {
        return;
    }
    ui->progressBarReceive->setValue(pos);
}

void BurnDlg3X::UpdateList()
{
    if (binModel == nullptr) {
        return;
    }
    int nRow = binModel->rowCount();
    if (nRow > 0x1000) {
        return;
    }
    std::vector<QString> pathArray;
    for (int i = 0; i < nRow; i++) {
        if (binModel->GetCheck(i)) {
            QString path = binModel->GetValue(i, TABLEVIEW_COLUMN_PAHT);
            pathArray.push_back(path);
        }
    }
    std::vector<QString> result;
    for (auto item : pathArray) {
        bool needAddDlg3X = true;
        for (auto item2 : result) {
            if (item2 == item) {
                needAddDlg3X = false;
                break;
            }
        }
        if (needAddDlg3X) {
            result.push_back(item);
        }
    }
    QString version;
    for (auto item : result) {
        BIN_INFO_ARRAY infoArray;
        DataConvertor::AnalysMultifBin(item, infoArray, version, isEncrypt, encryptBuffer);
        UpdateList(infoArray);
    }
}

void BurnDlg3X::UpdateList(BIN_INFO_ARRAY &info) const
{
    if (binModel == nullptr) {
        return;
    }
    for (int i = 0; i < info.GetSize(); i++) {
        BIN_INFO item = info.GetAt(i);
        int colNum = binModel->rowCount(); // 取行数
        if (colNum > 0x1000) {
            break;
        }
        QMap<int, BIN_INFO> mapBinInfo;
        mapBinInfo.clear();
        mapBinInfo = binModel->GetMapBinFileInfo();
        for (int j = 0; j < colNum; j++) {
            if ((!item.fileName.isEmpty()) && binModel->GetCheck(j) &&
                item.path == mapBinInfo[j].path && item.fileName == mapBinInfo[j].fileName &&
                item.type == mapBinInfo[j].type && (mapBinInfo[j].fileIndex != item.fileIndex ||
                mapBinInfo[j].fileSize != item.fileSize || mapBinInfo[j].burnAddr != item.burnAddr ||
                mapBinInfo[j].burnSize != item.burnSize)) {
                mapBinInfo[j].fileIndex = item.fileIndex;
                mapBinInfo[j].fileSize = item.fileSize;
                mapBinInfo[j].burnAddr = item.burnAddr;
                mapBinInfo[j].burnSize = item.burnSize;
            } else if (item.fileName.isEmpty() && binModel->GetCheck(j) && item.path == mapBinInfo[j].path &&
                       item.fileSize != mapBinInfo[j].fileSize) {
                mapBinInfo[j].fileSize = item.fileSize;
            }
        }
        binModel->FetchData(mapBinInfo);
    }
}

void BurnDlg3X::SlotShowQMessageBox(QString str)
{
    QMessageBox::warning(this, tr("warning"), str);
}

void BurnDlg3X::SlotBnClickedMultipleBurn()
{
    if (burnCtrl == nullptr || ui == nullptr) {
        return;
    }
    if (!isMultipleBurnOpen) {
        QMap<int, BIN_INFO> infoArray;
        GetCmdInfoArray(infoArray);
        if (infoArray.size() == 0) {
            QMessageBox::critical(this, stringClass.GetMessageError(),
                                  stringClass.GetIdsString33069(), stringClass.GetYes());
            return;
        }
        int result = QMessageBox::information(this, stringClass.GetInformation(),
                                              stringClass.GetIdsString33070(), stringClass.GetYes(),
                                              stringClass.GetNo());
        if (result == 1) {
            return;
        }
        burnCtrl->SetIsCancel(TRUE);
        burnCtrl->BurnCtrlCancel();
        isMultipleBurnOpen = true;
        if (burnCtrl->IsComOpen()) {
            emit SignalSendMsgInBurnDlg(static_cast<long int>(WiteThreadMsg::WITE_THREAD_MSG_RESETUIANDFSM), 0, 0);
        }
        ui->btnStartBurn->setEnabled(false);
        FillParamAndShow(infoArray);
    }
}

void BurnDlg3X::GetCmdInfoArray(QMap<int, BIN_INFO> &infoArray)
{
    if (binModel == nullptr) {
        return;
    }
    int nRow = binModel->rowCount();
    if (nRow > 0x1000) {
        return;
    }
    infoArray.clear();

    QMap<int, BIN_INFO> binInfo = binModel->GetMapBinFileInfo();
    QMap<int, bool> binCheck = binModel->GetMapCheck();
    int i = 0;
    for (auto it = binInfo.begin(); it != binInfo.end(); it++) {
        if (binCheck[it.key()] && it->type == IMAGE_TYPE::IMAGE_TYPE_LOADER) {
            BIN_INFO_ARRAY infoArrayBin;
            QString version;
            DataConvertor::AnalysMultifBin(ui->lineEditSeleteFile->text(), infoArrayBin, version,
                                           isEncrypt, encryptBuffer);
            PriorityBurn(infoArrayBin, infoArray, i);
        }

        if (binCheck[it.key()] &&
            (it->type == IMAGE_TYPE::IMAGE_TYPE_LOADER ||
            it->type >= IMAGE_TYPE::IMAGE_TYPE_APP_3321)) {
            infoArray[i++] = it.value();
        }
    }
}

void BurnDlg3X::FillParamAndShow(const QMap<int, BIN_INFO> &info)
{
    if (burnCtrl == nullptr || ui == nullptr) {
        return;
    }
    if (multipleBurnDlg != nullptr) {
        delete multipleBurnDlg;
        multipleBurnDlg = nullptr;
    }
    multipleBurnDlg = new MultipleBurnDlg();
    if (multipleBurnDlg == nullptr) {
        isMultipleBurnOpen = false;
        return;
    }
    int baud;
    int databits;
    int stopbits;
    QSerialPort::Parity parity;
    int flowctrl;
    multipleBurnDlg->SetChipType(chipType);
    multipleBurnDlg->SetSecConn(burnCtrl->IsSecConn());
    multipleBurnDlg->SetPeriod(burnCtrl->GetPeriod());
    burnCtrl->GetComSetting(baud, databits, stopbits, parity, flowctrl);
    multipleBurnDlg->UpdateComSetting(baud, databits, stopbits, parity, flowctrl);
    multipleBurnDlg->SetInfoArray(info);
    QString strFilePath = ui->lineEditSeleteFile->text();
    multipleBurnDlg->SetInfoArray(strFilePath);
    connect(multipleBurnDlg, &MultipleBurnDlg::SignalClose, this, &BurnDlg3X::SlotMultipleBurnDlgClose);
    multipleBurnDlg->SetCtrlNum(burnCtrl->GetMultiBurnTotalNum());
    multipleBurnDlg->SetOneLineNum(burnCtrl->GetMultiBurnNumPerLine());
    multipleBurnDlg->SetIndenpendentBurn(burnCtrl->GetMultiBurnIndenpendentBurn());
    multipleBurnDlg->SetIsResetAfterSuccess(burnCtrl->GetIsResetAfterSuccess());
    multipleBurnDlg->SetYModemEachPackageSize(burnCtrl->GetYModemEachPackageSize());
    multipleBurnDlg->InitUi();
    multipleBurnDlg->show();
}

void BurnDlg3X::SlotMultipleBurnDlgClose()
{
    if (ui == nullptr) {
        return;
    }
    isMultipleBurnOpen = false;
    ui->btnStartBurn->setEnabled(true);
}

void BurnDlg3X::SlotSettingSuccess()
{
    if (burnCtrl == nullptr) {
        return;
    }
    int baud;
    int databits;
    int stopbits;
    QSerialPort::Parity parity;
    int flowctrl;
    unsigned int totalNum;
    unsigned int numPerLine;
    bool indenpendent = false;
    bool reopenCom = false;
    bool isResetAfterSuccess = true;
    if (setting != nullptr) {
        setting->GetComConfig(baud, databits, stopbits, parity, flowctrl);
        burnCtrl->UpdateComSetting(baud, databits, stopbits, parity, flowctrl);
        burnCtrl->SetForceReadFlag(setting->GetForceRead());
        burnCtrl->SetYModemEachPackageSize(setting->GetYModemPackageSize());
        burnCtrl->SetForceReadTime(setting->GetForceReadTime());
        setting->GetMultipleBurnParam(totalNum, numPerLine, indenpendent, reopenCom);
        burnCtrl->SetMultiBurnTotalNum(totalNum);
        burnCtrl->SetMultiBurnNumPerLine(numPerLine);
        burnCtrl->SetMultiBurnIndenpendentBurn(indenpendent);
        setting->GetIsResetAfterSuccess(isResetAfterSuccess);
        burnCtrl->SetIsResetAfterSuccess(isResetAfterSuccess);
    }
}

void BurnDlg3X::SlotBnClickedSelectTarget()
{
    if (ui == nullptr) {
        return;
    }
    QString filePath = QFileDialog::getSaveFileName(this, tr("Select File"), "", stringClass.GetIdsString32949());
    if (!filePath.isEmpty()) {
        ui->lineEditSelectTarget->setText(filePath);
    }
}

void BurnDlg3X::SlotBnClickedExport()
{
    if (burnCtrl == nullptr || ui == nullptr) {
        return;
    }
    if (ui->btnExport->text() == stringClass.GetExportStart()) {
        if (burnCtrl == nullptr) {
            QMessageBox::critical(this, stringClass.GetMessageError(),
                                  stringClass.GetIdsString32984(), stringClass.GetYes());
            return;
        }
        if (burnCtrl->IsComOpen()) {
            QMessageBox::critical(this, stringClass.GetMessageError(),
                                  stringClass.GetIdsString32976(), stringClass.GetYes());
            return;
        }
        QString addr = ui->lineEditAddr->text();
        QString size = ui->lineEditLenth->text();
        QString path = ui->lineEditSelectTarget->text();
        U32 address = DataConvertor::Str2U32DecHex(addr);
        U32 lenth = DataConvertor::Str2U32DecHex(size);
        if (address == 0 || lenth == 0) {
            QMessageBox::critical(this, stringClass.GetMessageError(), tr("The address or length is incorrect."
                                                 "Check the entered length and address."), stringClass.GetYes());
            return;
        }
        burnCtrl->SetIsCancel(FALSE);
        ui->btnExport->setText(stringClass.GetExportStop());
        ui->textEditReceive->clear();
        ExportInfo *exportInfo = new ExportInfo();
        if (exportInfo == nullptr) {
            return;
        }
        exportInfo->addr = address;
        exportInfo->len = lenth;
        exportInfo->path = path;
        burnCtrl->SetComNum(ui->comboBoxCom->currentText().mid(3).toInt()); // 第3位为串口号
        emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_EXPORT),
                                    reinterpret_cast<WPARAM>(exportInfo),
                                    sizeof(exportInfo));
    } else {
        burnCtrl->SetIsCancel(TRUE);
        burnCtrl->BurnCtrlCancel();
    }
}

void BurnDlg3X::SlotExportFail()
{
    if (ui == nullptr) {
        return;
    }
    ui->btnExport->setText(stringClass.GetExportStart());
}

void BurnDlg3X::SlotExportSuccess()
{
    if (ui == nullptr) {
        return;
    }
    ui->progressBarReceive->setValue(SHRT_MAX);
    ui->btnExport->setText(stringClass.GetExportStart());
}

void BurnDlg3X::SlotBnClickedEraseAll()
{
    if (ui == nullptr || binModel == nullptr) {
        return;
    }
    ui->textEditReceive->clear();
    QMap<int, BIN_INFO> binInfo = binModel->GetMapBinFileInfo();
    QMap<int, BIN_INFO> checkBinInfo;
    QMap<int, bool> binCheck = binModel->GetMapCheck();
    int i = 0;
    for (auto it = binInfo.begin(); it != binInfo.end(); it++) {
        if (binCheck[it.key()] && it->type == IMAGE_TYPE::IMAGE_TYPE_LOADER) {
            BIN_INFO_ARRAY infoArray;
            QString version;
            DataConvertor::AnalysMultifBin(ui->lineEditSeleteFile->text(), infoArray, version,
                                           isEncrypt, encryptBuffer);
            checkBinInfo[i++] = it.value();
        }
    }
    burnCtrl->SetComNum(ui->comboBoxCom->currentText().mid(3).toInt()); // 第3位为串口号
    burnCtrl->InitBurnCmdByArray(checkBinInfo);
    ui->btnEraseAll->setEnabled(false);
    ui->btnStartBurn->setEnabled(false);
    ui->btnExport->setEnabled(false);
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_ERASE_ALL),
                                0,
                                0);
}

void BurnDlg3X::SlotEraseFail() const
{
    if (ui == nullptr) {
        return;
    }
    ui->btnEraseAll->setEnabled(true);
    ui->btnStartBurn->setEnabled(true);
    ui->btnExport->setEnabled(true);
}

void BurnDlg3X::SlotEraseSuccess() const
{
    if (ui == nullptr) {
        return;
    }
    ui->btnEraseAll->setEnabled(true);
    ui->btnStartBurn->setEnabled(true);
    ui->btnExport->setEnabled(true);
}

}
